﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Jack.DataScience.Http.Password;

namespace Vav.Data.Utils
{
    public class LoginEncryption
    {

        public Aes aes { get; set; }
        public LoginEncryption()
        {
            string key = "AcDl1ZcPIhf04D25hfxB8GMB2qj8RbGOmUZwYj+GW1k=";
            string iv = "+vamb9d4XgzAMipx5fFCsg==";
            aes = Aes.Create();
            aes.Key = Convert.FromBase64String(key);
            aes.IV = Convert.FromBase64String(iv);
        }
        public string Encrypt(UserLogin userLogin)
        {
            //2次编码
            var secret = HttpUtility.UrlEncode(HttpUtility.UrlEncode(aes.EncryptLogin(userLogin)));
            return secret;
        }
        public UserLogin Decrypt(string secret)
        {
            var login = aes.DecryptLogin(secret);
            return login;
        }
    }
    public static class UserLoginEncryptionExtensions
    {
        public static UserLogin DecryptLogin(this Aes aes, string value)
        {
            var data = Convert.FromBase64String(value);
            var decrypted = aes.CreateDecryptor().TransformFinalBlock(data, 0, data.Length);
            var json = Encoding.UTF8.GetString(decrypted);
            return JsonConvert.DeserializeObject<UserLogin>(json);
        }

        public static string EncryptLogin(this Aes aes, UserLogin userLogin)
        {
            var json = JsonConvert.SerializeObject(userLogin);
            var data = Encoding.UTF8.GetBytes(json);
            var encrypted = aes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
            return Convert.ToBase64String(encrypted);
        }


        #region Md5 
     
        /// <summary>
        /// Md5加密，加密后返回16进制加密结果(32位) 同时返回干扰码
        /// </summary>
        /// <param name="str"></param>
        /// <param name="passwordSalt"></param>
        /// <returns></returns>
        public static string Md5(this string str, out string passwordSalt)
        {
            passwordSalt = CreateSalt();
            return string.Concat(str, passwordSalt).ToMD5Hash().ToUpper();
        }
        /// <summary>
        /// Md5加密串校验
        /// </summary>
        /// <param name="mdString">md5字符串</param>
        /// <param name="str">待校验字符串</param>
        /// <param name="passwordSalt">混淆码</param>
        /// <returns>true 校验通过 false 失败</returns>
        public static bool Md5Check(this string mdString, string str, string passwordSalt)
        {
            return Md5(string.Concat(str, passwordSalt)) == mdString;
        }
        /// <summary>
        /// Md5加密，加密后返回16进制加密结果(32位)
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private static string Md5(string str)
        {
            return Md5(str, "utf-8");
        }

        /// <summary>
        /// Md5加密，加密后返回16进制加密结果(32位)
        /// </summary>
        /// <param name="str">待加密字符串</param>
        /// <param name="encode">编码类型：gb2312, utf-8, unicode等编码</param>
        /// <returns></returns>
        private static string Md5(string str, string encode)
        {
            var md5 = new MD5CryptoServiceProvider();
            byte[] bts = Encoding.GetEncoding(encode).GetBytes(str);
            byte[] md5Bts = md5.ComputeHash(bts);

            return BitConverter.ToString(md5Bts).Replace("-", "");
        }
        /// <summary>
        /// 创建干扰码
        /// </summary>
        /// <returns></returns>
        private static string CreateSalt()
        {
            var bytSalt = new byte[4];
            RNGCryptoServiceProvider rng;

            rng = new RNGCryptoServiceProvider();
            rng.GetBytes(bytSalt);

            return Convert.ToBase64String(bytSalt).ToUpper().Replace("=", "");
        }

        #endregion

    }

    public class UserLogin
    {
        public string Id { get; set; }
        public string Pass { get; set; }
        public string Time { get; set; } // format: yyyyMMddHHmm
    }


}
